package com.ruoyi.datastatistics.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.basedata.domain.RedisKeyName;
import com.ruoyi.basedata.domain.vo.TerminalsDbProtocol;
import com.ruoyi.basedata.service.ITerminalsDbService;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.CommonHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.datastatistics.domain.Realtimegatherdata;
import com.ruoyi.datastatistics.domain.TerminalHistoryData;
import com.ruoyi.datastatistics.domain.parsevo.PacketForRedis;
import com.ruoyi.datastatistics.service.IDeGaocallBackService;
import com.ruoyi.datastatistics.service.IRealtimegatherdataService;
import com.ruoyi.datastatistics.service.ITerminalHistoryDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 参数配置 服务层实现
 *
 * @author swdegao
 */
@Slf4j
@Service
public class DeGaocallBackServiceImpl implements IDeGaocallBackService
{
    @Autowired
    private RedisCache redisCache;
    /*@Autowired
    private CommonHelper commonHelper;*/
    @Autowired
    private ITerminalsDbService terminalsDbService;
    @Autowired
    private IRealtimegatherdataService realtimegatherdataService;
    @Autowired
    private ITerminalHistoryDataService terminalHistoryDataService;

    private static String factoryCode = "1002";

    @Override
    public void callBackNBSubscribe(String requestData)
    {
        if ("".equals(requestData)) return;
        PacketForRedis pr = nbIotpacketSaveTOJson(requestData);
        parsingMain(pr);
    }

    @Override
    public void callBackNettySubscribe(String requestData)
    {
        if ("".equals(requestData)) return;
        PacketForRedis pr = neetypacketSaveTOJson(requestData);
        parsingMain(pr);
    }

    public  void parsingMain(PacketForRedis packetForRedis)
    {
        try {
            String packetType = packetForRedis.packetType;
            JSONArray json = new JSONArray();
            String terminalAdd = packetForRedis.getTerminalId();//此处terminalid存的是通讯地址的值
            TerminalsDbProtocol terminalsDb = redisCache.getCacheMapValue(RedisKeyName.terminalDbInfo+factoryCode, terminalAdd);
            //跟据数据类型进行业务处理
            switch (Integer.parseInt(packetType))
            {
                case 97://0x61历史数据

                case 99://0x63历史数据

                    List<TerminalHistoryData> list = new ArrayList<TerminalHistoryData>();
                    try
                    {
                        //历史数据插入到redis中
                        terminalHistoryDataToRedis(list, packetForRedis, terminalsDb);
                        //log.Info(terminalAdd+"历史数据插入到redis中");
                    }
                    catch (Exception e)
                    {
                        log.error(packetForRedis.imei+"历史数据插入到redis中异常" + e.getMessage());
                    }
                    try
                    {
                        //更新设备、包括redis、数据库  去掉，数据库中表档案无需更新
                        synchronousMostValueFromRealtimegatherdata(list, terminalsDb);
                        //log.Info(terminalAdd+"更新设备、包括redis、数据库");
                    }
                    catch (Exception e)
                    {
                        log.error(packetForRedis.imei+"更新设备、包括redis、数据库异常" + e.getMessage());
                    }
                    try
                    {
                        //将历史数据批量插入数据库
                        InsertTerminalHistoryData(list,terminalsDb);
                        //log.Info(terminalAdd+"历史数据批量插入数据库");
                    }
                    catch (Exception e)
                    {
                        log.error(packetForRedis.imei+"历史数据批量插入数据库异常" + e.getMessage());
                    }
                    try {
                        removeTerminalHistoryDataInRedis(terminalsDb);
                    } catch (Exception e)
                    {
                        log.error(packetForRedis.imei + "removeRealtimeDataInRedis异常" + e.getMessage());
                    }


                    break;
                case 101://0x65预警
                    try
                    {
                        /*IList<Object> alarmList = new List<Object>();
                        alarmList.Add(packetForRedis);
                        JArray alarmJson = JArray.FromObject(alarmList);
                        _alarmService.InsertAlarmDataForRedis(alarmJson, realtimeDetailDataForRedis, con);*/
                    }
                    catch (Exception e)
                    {
                        log.error(packetForRedis.imei+"预警异常" + e.getMessage());

                    }

                    break;
                case 102://0x66定位
                    try {
                        //json = new JArray();
                        //json.Add(packetForRedis);
                     /*   IList<Object> positionList = new List<Object>();
                        positionList.Add(packetForRedis);
                        JArray positionJson = JArray.FromObject(positionList);
                        _realtimeGPSDataService.InsertGPSDataForRedis(positionJson, realtimeDetailDataForRedis, con);*/
                    } catch (Exception e) {
                        log.error(packetForRedis.imei+"定位异常" + e.getMessage());
                    }

                    break;
                case 103://0x67日用量
                    try {
                       // _FreezeDayAnalysisByRedisService.FreezeDayAnalysis(packetForRedis, realtimeDetailDataForRedis, redis);
                    } catch (Exception e)
                    {
                        log.error(packetForRedis.imei+"日用量处理异常" + e.getMessage());
                    }

                    break;
                case 0x92:
                    JSONObject data = packetForRedis.jsonData;
                    String imei = data.getString("IMEI");
                    // var query = from Terminals in this._terminals.Table
                    // join UserTerminals in this._userTerminals.Table on Terminals.Id equals UserTerminals.TerminalID
                    // where Terminals.IMEI.Equals(IMEI) where Terminals.TerminalMark < 2
                    // select UserTerminals;
                    // List<UserTerminals> userTerminals = query.ToList();
                    Realtimegatherdata realtimeTerminalData = new Realtimegatherdata();
                    // if (userTerminals.Count == 1)
                    // {
                    //     realtimeTerminalData.UserTermianlID = userTerminals[0].Id;
                    // }
                    // else
                    // {
                    //     return;
                    // }
                    // realtimeTerminalData.TerminalFactoryID = data["TerminalFactoryID"] == null ? null : data["TerminalFactoryID"].ToString();
                    // realtimeTerminalData.CateGory = data["CateGory"] == null ? null : data["CateGory"].ToString();
                    // realtimeTerminalData.Version = data["Version"] == null ? null : data["Version"].ToString();
                    realtimeTerminalData.setImei(imei);
                    // realtimeTerminalData.ICCID = data["ICCID"] == null ? null : data["ICCID"].ToString();
                    // realtimeTerminalData.IMSI = data["IMSI"] == null ? null : data["IMSI"].ToString();
                    // realtimeTerminalData.SIMOperator = data["SIMOperator"] == null ? null : data["SIMOperator"].ToString();
                    // realtimeTerminalData.SIMCateGory = data["SIMCateGory"] == null ? null : data["SIMCateGory"].ToString();
                    // realtimeTerminalData.MainCenter = data["MainCenter"] == null ? null : data["MainCenter"].ToString();
                    // realtimeTerminalData.SubCenter = data["SubCenter"] == null ? null : data["SubCenter"].ToString();
                    // realtimeTerminalData.MainIP = data["MainIP"] == null ? null : data["MainIP"].ToString();
                    // realtimeTerminalData.SubIP = data["SubIP"] == null ? null : data["SubIP"].ToString();
                    // realtimeTerminalData.AlarmInfo = data["AlarmInfo"] == null ? null : data["AlarmInfo"].ToString();
                    // realtimeTerminalData.MainPort = data["MainPort"] == null ? null : data["MainPort"].ToString();
                    // realtimeTerminalData.MainType = data["MainType"] == null ? null : data["MainType"].ToString();
                    // realtimeTerminalData.SubPort = data["SubPort"] == null ? null : data["SubPort"].ToString();
                    // realtimeTerminalData.SubType = data["SubType"] == null ? null : data["SubType"].ToString();


                    if (StringUtils.isNotBlank(data.getString("TerminalTime")))
                    {
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
                        realtimeTerminalData.setReadDate(simpleDateFormat.parse(data.getString("TerminalTime")));;
                    }
                    if (StringUtils.isNotBlank(data.getString("CSQ")))
                    {
                        realtimeTerminalData.setTerminalCsq(Long.parseLong(data.getString("CSQ")));
                    }
                    if (StringUtils.isNotBlank(data.getString("ReadNumber")))
                    {
                        realtimeTerminalData.setReadNumber(new BigDecimal(data.getString("ReadNumber")));
                    }
                    if (StringUtils.isNotBlank(data.getString("ReverseNumber")))
                    {
                        realtimeTerminalData.setReverseNumber(new BigDecimal(data.getString("ReverseNumber")));
                    }
                    if (StringUtils.isNotBlank(data.getString("TotalFlow")))
                    {
                        realtimeTerminalData.setTotalFlow(new BigDecimal(data.getString("TotalFlow")));
                    }
                    if (StringUtils.isNotBlank(data.getString("InstantNumber")))
                    {
                        realtimeTerminalData.setInstantNumber(new BigDecimal(data.getString("InstantNumber")));
                    }
                    if (StringUtils.isNotBlank(data.getString("Pressure")))
                    {
                        realtimeTerminalData.setPressure(new BigDecimal(data.getString("Pressure")));
                    }
                    if (StringUtils.isNotBlank(data.getString("TerminalVol")))
                    {
                        realtimeTerminalData.setTerminalVol(new BigDecimal(data.getString("TerminalVol")));
                    }
                    // if (data["MeteringVol"] != null)
                    // {
                    //     realtimeTerminalData.MeteringVol = (decimal)data["MeteringVol"];
                    // }
                    // if (data["Acquisitioncycle"] != null)
                    // {
                    //     realtimeTerminalData.Acquisitioncycle = (int)data["Acquisitioncycle"];
                    // }
                    // if (data["Reportingcycle"] != null)
                    // {
                    //     realtimeTerminalData.Reportingcycle = (int)data["Reportingcycle"];
                    // }
                    // if (data["State"] != null)
                    // {
                    //     realtimeTerminalData.State = (int)data["State"];
                    // }
                    if (StringUtils.isNotBlank(data.getString("Valve")))
                    {
                        int valveState = data.getIntValue("Valve");
                        realtimeTerminalData.setValveState(valveState==1?0:1);
                    }
                    realtimeTerminalData.setCreateTime(new Date());
                    realtimegatherdataService.insertRealtimegatherdata(realtimeTerminalData);
                /* 您可以有任意数量的 case 语句 */
                default: /* 可选的 */

                    break;
            }

        } catch (Exception e)
        {
        }

    }
    //历史数据插入到redis中
    public  void terminalHistoryDataToRedis(List<TerminalHistoryData> list, PacketForRedis packetForRedis, TerminalsDbProtocol terminalsDb)
    {
        String errorflag = "200";
        try
        {
            JSONObject packet = packetForRedis.getJsonData();
            BigDecimal CumulantiveRate = new BigDecimal(1);
            errorflag = joiningTerminalpackage(list, packet, CumulantiveRate, terminalsDb);
            packetForRedis.actionStatus = errorflag;
            packetForRedis.insertime = ConvertDateTimeToInt(new Date());
            // redis.ListRightPush(RedisKeyName.InsertOver+ realtimeDetailDataForRedis.TerminalAddress, packetForRedis);
        }catch (Exception e)
        {
            errorflag = "508";//未知bug
            log.error(e.getMessage()+packetForRedis.toString());
        }
    }
    //历史数据插入到redis中
    public String joiningTerminalpackage(List<TerminalHistoryData> list,JSONObject json,BigDecimal CumulantiveRate, TerminalsDbProtocol terminalsDb) throws ParseException {
        Boolean isAddRow = true;

        String flag = "200";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        //RedisHelp.RedisHelper redis = new RedisHelp.RedisHelper(1);
        if (json != null)
        {
            Date prevTime = null;
            BigDecimal prevTotalFlow = null;
            String date = json.get("date").toString();
            String date_ = getPackageDate(date);//返回格式年月日
            String type = json.get("type").toString();
            JSONArray info = json.getJSONArray("info");
            String voltage = json.getString("voltage");
            String signal1 = json.getString("signal1");
            String signal = json.getString("signal");
            String msgId = json.getString("msgId");

            for (int j = 0; j < info.size(); j++)
            {
                JSONObject temp_jo = info.getJSONObject(j);
                String time = temp_jo.getString("time");
                Integer num = Integer.parseInt(temp_jo.getString("num"));//本组中包含多少条数据
                Integer density = temp_jo.get("density") != null ? Integer.parseInt(temp_jo.getString("density")) : 15;//本组包获取密度
                time = getPackageTime(time, date_);//返回info中第一组time 得时间，格式年月日时分秒

                JSONArray dsinfo = temp_jo.getJSONArray("dsinfo");

                Date TerminalTime = null;
                try
                {

                    TerminalTime = sdf.parse(time);
                }
                catch (Exception e)
                {
                    flag = "501";
                    log.error(terminalsDb.getTerminalId() + "@@TerminalTime:" + e.getMessage());
                    continue;
                }


                if (TerminalTime == null)
                    continue;
                for (int k = 0; k < dsinfo.size(); k++)
                {
                    TerminalHistoryData realtimegatherdata = new TerminalHistoryData();
                    try
                    {
                        JSONObject job = dsinfo.getJSONObject(k);
                        isAddRow = true;

                        BigDecimal TotalFlow = null;
                        BigDecimal ReadNumber = null;
                        BigDecimal ReverseNumber = null;
                        BigDecimal InstantNumber = null;
                        BigDecimal Pressure = null;
                        BigDecimal InstantVelocity = null;

                        BigDecimal TerminalVol = null;
                        Integer TerminalCSQ = null;
                        try
                        {
                            try
                            {
                                realtimegatherdata.setReadNumber(!job.get("ReadNumber").equals("") ? new BigDecimal(job.getString("ReadNumber")) : ReadNumber);
                                realtimegatherdata.setReverseNumber(!job.get("ReverseNumber").equals("") ? new BigDecimal(job.getString("ReverseNumber")) : ReverseNumber);
                                realtimegatherdata.setInstantNumber(!job.get("InstantNumber").equals("") ? new BigDecimal(job.getString("InstantNumber")) : InstantNumber);
                                realtimegatherdata.setTotalFlow(!job.get("TotalFlow").equals("") ? new BigDecimal(job.getString("TotalFlow")) : TotalFlow);
                            }
                            catch (Exception e)
                            {
                                log.error(terminalsDb.getImei() + "@@流量解析异常" + e.getMessage());
                            }
                            try
                            {
                                realtimegatherdata.setPressure(job.get("Pressure") != null && job.getString("Pressure").matches( "[\\d]*[.][\\d]*") ? new BigDecimal(job.getString("Pressure")) : Pressure);
                            }
                            catch (Exception e)
                            {
                                log.error(terminalsDb.getImei() + "@@压力解析异常" + e.getMessage());
                            }
                            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                          //  realtimegatherdata.setInstantVelocity(job.get("InstantVelocity")!=null ? new BigDecimal(job.getString("InstantVelocity")) : TotalFlow);
                           // realtimegatherdata.ElectromagneticPressure = job["ElectromagneticPressure"] != null && !job["ElectromagneticPressure"].ToString().Contains("NaN") ? decimal.Round(Convert.ToDecimal(Convert.ToDouble(job["ElectromagneticPressure"])), 2) : 99;
                           // realtimegatherdata.ElectromagneticPressureType = job["ElectromagneticPressureType"] != null && !job["ElectromagneticPressureType"].ToString().Contains("NaN") ? Convert.ToInt32(job["ElectromagneticPressureType"]) : 1;
                            realtimegatherdata.setLocationNb(terminalsDb.getLocationNb());
                            realtimegatherdata.setTerminalId(terminalsDb.getTerminalId());
                           // realtimegatherdata.setRoomId(terminalsDb.getRoomId());
                            realtimegatherdata.setTenantId(terminalsDb.getTenantId());
                            realtimegatherdata.setTerminalVol(!json.get("voltage").equals("")? new BigDecimal(json.getString("voltage")) : TerminalVol);
                            realtimegatherdata.setTerminalCsq(!signal1.equals("")? new Long(signal1) : TerminalCSQ);
                            realtimegatherdata.setTerminalCsqDescribe(signal);
                            realtimegatherdata.setValveState(1L);
                            //realtimegatherdata.setTerminalTime(sdf.format(TerminalTime));
                            realtimegatherdata.setReadDate(TerminalTime);
//                            realtimegatherdata.setCreateDate(new Date());
                            //是否为机械大表
                            if ("1".equals(type) && CumulantiveRate != null)
                            {
                                realtimegatherdata.setTotalFlow(realtimegatherdata.getTotalFlow().multiply(CumulantiveRate));
                            }
                        }
                        catch (Exception e)
                        {
                            flag = "502";
                            log.error(terminalsDb.getImei()  + "@@502" + e.getMessage());
                        }

                        //计算瞬时流量
                        if (null == realtimegatherdata.getReadNumber() && null == realtimegatherdata.getReverseNumber() && null == realtimegatherdata.getTotalFlow() && null == realtimegatherdata.getPressure())
                        {
                            isAddRow = false;
                        }

                        try
                        {
                            if (true)
                              //  if (!realtimeDetailDataForRedis.ServerIndex1.HasValue || 0 == realtimeDetailDataForRedis.ServerIndex1.Value)
                            {
                                double d_TimeSpan = 0;//两条数据间时间间隔
                                try
                                {
                                    if (prevTime==null)
                                    {
                                        if (prevTotalFlow != null)
                                            realtimegatherdata.setInstantNumber( (realtimegatherdata.getTotalFlow().subtract(prevTotalFlow)).multiply(new BigDecimal(60)).divide(new BigDecimal(density)) );
                                    }
                                    else
                                    {
                                        d_TimeSpan = Math.abs((TerminalTime.getTime()-prevTime.getTime())/1000/60);//两条数据间时间间隔
                                        if (d_TimeSpan == density && prevTotalFlow != null)
                                            realtimegatherdata.setInstantNumber( (realtimegatherdata.getTotalFlow().subtract(prevTotalFlow)).multiply(new BigDecimal(60)).divide(new BigDecimal(density)) );

                                    }
                                }
                                catch (Exception e)
                                {
                                    flag = "504";
                                    log.error(terminalsDb.getImei() + "@@504" + e.getMessage());
                                }
                                //对第一个瞬时流量点异常处理
                                if (j == 0 && k == 1 && Integer.parseInt(type) == 2 && list.size() > 0)//第一个点异常处理
                                {
                                    BigDecimal firstIns = list.get(0).getInstantNumber();
                                    if (firstIns != null)
                                    {
                                        try
                                        {
                                            BigDecimal secondIns = realtimegatherdata.getInstantNumber();
                                            if (secondIns.subtract(new BigDecimal(0)) != new BigDecimal(0) && firstIns.subtract(new BigDecimal(0)) != new BigDecimal(0))
                                            {
                                                //BigDecimal firstIns_ = firstIns.subtract(secondIns).abs().divide(secondIns).compareTo(new BigDecimal(0.05))>0? secondIns : firstIns;
                                                list.get(0).setInstantNumber(firstIns.subtract(secondIns).abs().divide(secondIns).compareTo(new BigDecimal(0.05))>0? secondIns : firstIns);
                                            }
                                            //针对与自主研发，第一个包的第一瞬时流量有问题，更新bykyx
                                            if (secondIns.compareTo(new BigDecimal(0)) == 0&& TotalFlow.compareTo(new BigDecimal(0)) == 0)
                                            {
                                                list.get(0).setInstantNumber(new BigDecimal(0));
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            flag = "503";
                                            log.error(terminalsDb.getImei() + "@@++++++" + e.getMessage());
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            flag = "508";
                            log.error(terminalsDb.getImei()+ "获取瞬时流量计算异常" + e.getMessage());
                        }
                        //每条数据中得冻结时间与数据包冻结时间对比，新协议中才有此时间newdate ->yyyy
                        String detailsTime = job.get("detailsTime") != null ? (!job.getString("detailsTime").equals("") ? sdf.format(new Date()).substring(0, 2) + job.getString("detailsTime") : "") : "";

                        //没有验证时间或者验证时间与数据包冻结时间相同
                        if ((detailsTime.equals("") || detailsTime.equals(date_)) && isAddRow)
                        {
                            Boolean flag2 = checkIsSaveInRedis(terminalsDb.getCommunicateAddress(), TerminalTime);
                            if (!flag2)
                            {
                                list.add(realtimegatherdata);
                                //插入到redis中

                                redisCache.SortedSetAdd(RedisKeyName.backupDB_HistoricalData+factoryCode+"_" + terminalsDb.getCommunicateAddress(),JSONObject.from(realtimegatherdata), ConvertDateTimeToInt(realtimegatherdata.getReadDate()));
                            }

                        }
                        else
                        {
                            //设备冻结时间不成功时，prevTotalFlow为零瞬时流量不进行计算 /20210515/kyx
                            prevTotalFlow = null;
                            flag = "505";
                            log.error("数据解析失败505-终端地址：" + terminalsDb.getTerminalId() + " detailsTime:" + detailsTime + " date_:" + date_ + " isAddRow:" + isAddRow);
                        }
                        //验证newdt中是否已经存在TerminalTime的数据2019-05-27
                        prevTime = TerminalTime;
                        prevTotalFlow = realtimegatherdata.getTotalFlow();
                        TerminalTime = addMinutes(TerminalTime,density);
                    }
                    catch (Exception e)
                    {
                        flag = "506";
                        log.error(terminalsDb.getTerminalId() + "joiningTerminalpackage抛出异常：" + e.getMessage());
                    }

                }
            }
        }
        return flag;
    }

    /**
     * 更新实时数据表
     * @param list
     * @param terminalsDb
     */
    public void synchronousMostValueFromRealtimegatherdata(List<TerminalHistoryData> list,TerminalsDbProtocol terminalsDb){

        if(list.size()>0){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Realtimegatherdata realtimegatherdata = new Realtimegatherdata();
            realtimegatherdata.setLocationNb(terminalsDb.getLocationNb());
            List<Realtimegatherdata> isupate = realtimegatherdataService.selectRealtimegatherdataList(realtimegatherdata);

            TerminalHistoryData t = list.get(list.size()-1);
            realtimegatherdata.setReadNumber(t.getReadNumber());
            realtimegatherdata.setReverseNumber(t.getReverseNumber());
            realtimegatherdata.setInstantNumber(t.getInstantNumber());
            realtimegatherdata.setTotalFlow(t.getTotalFlow());
            realtimegatherdata.setPressure(t.getPressure());
            realtimegatherdata.setLocationNb(t.getLocationNb());
            realtimegatherdata.setTerminalId(t.getTerminalId());
//            realtimegatherdata.setRoomId(terminalsDb.getRoomId());
            realtimegatherdata.setTenantId(t.getTenantId());
            realtimegatherdata.setTerminalVol(t.getTerminalVol());
            realtimegatherdata.setTerminalCsq(t.getTerminalCsq());
            realtimegatherdata.setTerminalCsqDescribe(t.getTerminalCsqDescribe());
            realtimegatherdata.setValveState(new Integer(1));
//            realtimegatherdata.setTerminalTime(sdf.format(t.getCreateDate()));
            realtimegatherdata.setReadDate(t.getReadDate());

            if(isupate.size()>0){
                //更新
                realtimegatherdataService.updateRealtimegatherdata(realtimegatherdata);
            }else{
                //插入
                realtimegatherdataService.insertRealtimegatherdata(realtimegatherdata);
            }
        }
    }
    /**
     * 时间添加
     * @param date
     * @param minutes
     * @return
     */
    public static Date addMinutes(Date date, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }
    /// <summary>
    /// 是否再redis中存储，false没有存储，true已经存储
    /// </summary>
    /// <param name="terminaladd"></param>
    /// <param name="stratTime"></param>
    /// <returns></returns>
    public Boolean  checkIsSaveInRedis(String terminaladd, Date stratTime)
    {
        Boolean flag = false;
        long time = ConvertDateTimeToInt(stratTime);
        Set<Realtimegatherdata> list = redisCache.SortedSetRangeByRank(RedisKeyName.backupDB_HistoricalData+factoryCode+"_" + terminaladd, ConvertDateTimeToInt(stratTime), ConvertDateTimeToInt(stratTime));
        if(null != list && list.size() > 0)
        {
            flag = true;
        }
        return flag;
    }
    /**
     * 时间处理
     * @param date
     * @return
     * @throws ParseException
     */
    public String getPackageDate(String date) throws ParseException {
        String date_ = "";//时间 临时
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        if (!date.equals("")) date_ = date.length() > 4 ? sdf.format( new Date()).substring(0, 2) + date : sdf.format( new Date()) + date;
        sdf = new SimpleDateFormat("yyyyMMdd");
        Date dt = sdf.parse(date_);

        if (dt.compareTo(new Date())>0)
        {
            String year = new Date().getYear() - 1 + "";
            date = date.length() > 4 ? date_ : year + date;

        }
        else
        {
            date = date_;
        }
        return date;
    }

    /**
     * 时间处理
     * @param time
     * @param date
     * @return
     */
    public String getPackageTime(String time, String date)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        time = time.length() < 2 ? "0" + time : time;
        time = time.length() < 4 ? (date + time + "0000") : sdf.format( new Date()).substring(0, 2) + time + "00";
        return time;
    }
    /// <summary>
    /// 插入日冻结数据
    /// </summary>
    /// <param name="dt"></param>
    /// <param name="con"></param>
    /// <returns></returns>
    public  boolean InsertTerminalHistoryData(List<TerminalHistoryData> list,TerminalsDbProtocol terminalsDb )
    {
        boolean copy = false;
        if(list.size()>0)
            terminalHistoryDataService.batchinsertTerminalHistoryData(list);
            //realtimegatherdataService.batchinsertRealtimegatherdata(list);
        return copy;
    }
    /// <summary>
    /// 清理redis中数据
    /// </summary>
    /// <param name="terminalAdd"></param>
    public void removeTerminalHistoryDataInRedis(TerminalsDbProtocol terminalsDb)
    {
        try
        {
            Set<Realtimegatherdata> firt_list = redisCache.SortedSetRangeByRank(RedisKeyName.backupDB_HistoricalData + factoryCode + "_" + terminalsDb.getCommunicateAddress(), 0, 0);
            if (firt_list != null && firt_list.size() > 0)
            {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Long interval = new Date().getTime()  - sdf.parse(firt_list.stream().findFirst().get().getTerminalTime()).getTime() ;
                if (interval/(24 * 60 * 60 * 1000) > RedisKeyName.backupDB_HistoricalData_days)
                {
                    long st = new Date().getTime()-RedisKeyName.backupDB_HistoricalData_days*(24 * 60 * 60 * 1000);
                    redisCache.SortedSetRemoveByScore(RedisKeyName.backupDB_HistoricalData + factoryCode + "_"+ terminalsDb.getCommunicateAddress(), sdf.parse(firt_list.stream().findFirst().get().getTerminalTime()).getTime(), st);

                }
            }


        }
        catch (Exception e)
        {
            log.error(terminalsDb.getTerminalId() + "历史数据清理异常" + e.getMessage());
        }
    }

    /**
     * nb回调数据解析成PacketForRedis
     * @param requestData
     * @return
     */
    public  PacketForRedis nbIotpacketSaveTOJson(String requestData)
    {
        String terminalAdd = "";
        PacketForRedis packetForRedis = new PacketForRedis();
        try
        {
           // var jo_ = JsonConvert.DeserializeObject(requestData);
            JSONObject jo = JSONObject.parseObject(requestData);
            byte[] data = null;
            String data_ = jo.getJSONObject("payload").getJSONObject("serviceData").getString("upData");
            data = hexStringToByteArray(data_);
            terminalAdd = getTerminalAdd(data);//截取地址
            String deviceId = jo.getString("deviceId");
            String imei = jo.getString("IMEI");
            packetForRedis = getPacketForRedis(data,terminalAdd,imei,requestData);
            //获取设备基础信息，获取属性协议
           /* String aDllName = "";
            String aClassName = "";
            TerminalsDbProtocol terminalsDb = new TerminalsDbProtocol();

            try
            {
                if (!redisCache.hmhave(RedisKeyName.terminalInfo+factoryCode, terminalAdd))//redis中是否存在该设备
                {

                    terminalsDb = terminalsDbService.selectTerminalsDbProtocolList(terminalsDb).get(0);
                    if (terminalsDb != null)
                    {
                        //RealtimeDetailDataForRedis = getRealtimeDetailDataForRedis(terminalAdd);
                        redisCache.setCacheMapValue(RedisKeyName.terminalInfo+factoryCode, terminalAdd, terminalsDb);
                        aClassName = terminalsDb.getClassName();
                    }
                    else
                    {
                        //若是数据库里查找不到档案，记录到解析日志表中
                        redisCache.lPush(RedisKeyName.exceptions + factoryCode+terminalAdd, requestData);//记录异常
                    }
                }
                else
                {
                    terminalsDb = redisCache.getCacheMapValue(RedisKeyName.terminalInfo+factoryCode, terminalAdd);
                    aClassName = terminalsDb.getClassName();
                }
            }
            catch (Exception e)
            {
                redisCache.lPush(RedisKeyName.exceptions + factoryCode + terminalAdd, requestData);//记录异常
                redisCache.trim(RedisKeyName.exceptions + factoryCode  + terminalAdd, -4, -1);//删除exceptions数据

                return null;
            }
            if ("".equals(aClassName)) aClassName = "IDeGaocallBackService";
            //解析成json,存储到redis
            Object[] param = { data };
            JSONObject temp = getPacketForRedis(data,aClassName);

            // JObject json_packet = JObject.FromObject(temp);
            int packetType = data[9];

            packetForRedis = new PacketForRedis();
            packetForRedis.setImei(imei);
            packetForRedis.setPacketType(packetType+ "");
            packetForRedis.setJsonData(temp);
            packetForRedis.setNettycreatetime(ConvertDateTimeToInt(new Date()));
            packetForRedis.setTerminalId(terminalAdd);*/

           // redisCache.lPush(RedisKeyName.WaitingPacketInsert + terminalAdd, packetForRedis);
        }
        catch (Exception e)
        {
            redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, requestData);//记录异常
            redisCache.trim(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, -4, -1);//删除exceptions数
        }
        return packetForRedis;
    }
    /**
     * netty回调数据解析成PacketForRedis
     * @param requestData
     * @return
     */
    public  PacketForRedis neetypacketSaveTOJson(String requestData)
    {
        String terminalAdd = "";
        PacketForRedis packetForRedis = new PacketForRedis();
        try
        {
            // var jo_ = JsonConvert.DeserializeObject(requestData);
            JSONObject jo = JSONObject.parseObject(requestData);
            byte[] data = null;
            if(jo.get("upDataList") != null){
                String data_ = jo.getJSONArray("upDataList").getJSONObject(0).getString("upData");
                data = hexStringToByteArray(data_);
               // log.info(data_);
                terminalAdd = getTerminalAdd(data);//截取地址
                String imei = jo.getString("imei");
                //获取设备基础信息，获取属性协议
                packetForRedis = getPacketForRedis(data,terminalAdd,imei,requestData);
                // redisCache.lPush(RedisKeyName.WaitingPacketInsert + terminalAdd, packetForRedis);
            }

        }
        catch (Exception e)
        {
            redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, requestData);//记录异常
            redisCache.trim(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, -4, -1);//删除exceptions数
        }
        return packetForRedis;
    }
    private PacketForRedis getPacketForRedis(byte[] data,String terminalAdd,String imei,String requestData){
        String aClassName = "";
        TerminalsDbProtocol terminalsDb = new TerminalsDbProtocol();

        try
        {
            if (!redisCache.hmhave(RedisKeyName.terminalDbInfo+factoryCode, terminalAdd))//redis中是否存在该设备
            {
                terminalsDb.setCommunicateAddress(terminalAdd);
//                terminalsDb.setSupplierId(factoryCode);
                terminalsDb = terminalsDbService.selectTerminalsDbProtocolList(terminalsDb).get(0);
                if (terminalsDb != null)
                {
                    //RealtimeDetailDataForRedis = getRealtimeDetailDataForRedis(terminalAdd);
                    redisCache.setCacheMapValue(RedisKeyName.terminalDbInfo+factoryCode, terminalAdd, terminalsDb);
                    aClassName = terminalsDb.getClassName();

                }
                else
                {
                    //若是数据库里查找不到档案，记录到解析日志表中
                    redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_"+terminalAdd, requestData);//记录异常
                }
            }
            else
            {
                terminalsDb = redisCache.getCacheMapValue(RedisKeyName.terminalDbInfo+factoryCode, terminalAdd);
                aClassName = terminalsDb.getClassName();
            }
        }
        catch (Exception e)
        {
            redisCache.lPush(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, requestData);//记录异常
            redisCache.trim(RedisKeyName.exceptions + factoryCode + "_" + terminalAdd, -4, -1);//删除exceptions数据
            return null;
        }

        if ("".equals(aClassName)||null==aClassName) //aClassName = "com.ruoyi.datastatistics.service.impl.DeGaocallBackServiceImpl";
            aClassName = "com.ruoyi.datastatistics.Agreement.DeGaoNettyV35";
        //解析成json,存储到redis
        Object param = data ;
        JSONObject temp = getPacketForRedis(data,aClassName);

        // JObject json_packet = JObject.FromObject(temp);
        int packetType = data[9];

        PacketForRedis packetForRedis = new PacketForRedis();
        packetForRedis.setImei(imei);
        packetForRedis.setPacketType(packetType+ "");
        packetForRedis.setJsonData(temp);
        packetForRedis.setNettycreatetime(ConvertDateTimeToInt(new Date()));
        packetForRedis.setTerminalId(terminalAdd);
        return packetForRedis;
    }
    /**
     * 解析数据包
     * @param data
     * @param aClassName
     * @return
     */
    private JSONObject getPacketForRedis(byte[] data,String aClassName)
    {
        JSONObject jo = new JSONObject();
        Object[] param ={ data };
        if ((byte)data[9] == 0x63 || (byte)data[9] == 0x61)
        {
            Object temp = CommonHelper.getMethod(aClassName,"GetBufferPacketForAll", param);
            jo = (JSONObject) temp;

        }
        else if ((byte)data[9] == 0x65)
        {
            //预警包
            Object temp = CommonHelper.getMethod(aClassName, "GetBufferPacketForWarning", param);
            jo = (JSONObject) temp;
        }
        else if ((byte)data[9] == 0x66)
        {
            //定位包
            Object temp = CommonHelper.getMethod(aClassName, "GetBufferPacketForGPS", param);
            jo = (JSONObject) temp;
        }
        else if ((byte)data[9] == 0x67)
        {
            //日冻结包
            Object temp = CommonHelper.getMethod(aClassName, "GetBufferPacketForFreezeDay", param);
            jo = (JSONObject) temp;
        }
        return jo;
    }
    /**
     * DateTime时间格式转换为Unix时间戳格式
     * @param time
     * @return
     */
    public long ConvertDateTimeToInt(Date time)
    {
        long timeInMillis = time.getTime();
        long unixTime = timeInMillis / 1000;
        return unixTime;
    }

    public static byte[] hexStringToByteArray(String hexString) {
        hexString = hexString.replaceAll(" ", "");
        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个字节
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
                    .digit(hexString.charAt(i+1), 16));
        }
        return bytes;
    }
    private byte[] hexStringToByte(String hex)
    {
        int len = (hex.length() / 2); //除以2是因为十六进制比如a1使用两个字符代表一个byte
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++)
        {
            //乘以2是因为十六进制比如a1使用两个字符代表一个byte,pos代表的是数组的位置
            //第一个16进制数的起始位置是0第二个是2以此类推
            int pos = i * 2;
            //<<4位就是乘以16  比如说十六进制的"11",在这里也就是1*16|1,而其中的"|"或运算就相当于十进制中的加法运算
            //如00010000|00000001结果就是00010001 而00010000就有点类似于十进制中10而00000001相当于十进制中的1，与是其中的或运算就相当于是10+1(此处说法可能不太对，)
            result[i] = (byte)(toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }
    private byte toByte(char c)
    {
        byte b = (byte)"0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * 获取设备地址
     * @param bit
     * @return
     */
    private String getTerminalAdd(byte[] bit)
    {
        byte[] bit_add = new byte[4];
        System.arraycopy(bit, 5, bit_add, 0, 4);
        int  temp = Integer.parseInt(getIntFromByte2(bit_add));//终端地址
        return temp+"";
    }

    /**
     * 两位不足 补零,高位在hou,eg->0x0c 0x02:0c02
     * @param bit
     * @return
     */
    public static String getIntFromByte2(byte[] bit)
    {
        String str = "";
        for (int i = 0; i < bit.length; i++)
        {
            String temp = Integer.toHexString(bit[i]& 0xFF);
            temp = temp.length() < 2 ? ("0" + temp) : temp;
            str = str + temp;
        }
        return str;
    }

}
